﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data.SqlClient;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Web.Configuration;
using System.Web.Http;
using System.Web.Http.Controllers;
using Common.Logging;
using In.Api.Dto.HisWs;
using Newtonsoft.Json;
using OutDbContext;
using Rmq.Center;
using Senparc.Weixin.MP.TenPayLib;
using User.Api.BizExtensions;
using User.Api.Dto.Reg;
using User.Api.Helpers;
using User.Api.HttpClients;

namespace User.Api.Controllers
{
    public class RegController : ApiController
    {
        private static readonly ILog Logger = LogManager.GetLogger(typeof(RegController));
        private FsssdqfybjyEntities _ctx;

        private static readonly object OrderNoLocker = new object();
        private static readonly object PayNotifyLocker = new object();

        private static TenPayInfo _tenPayInfo;

        public static TenPayInfo TenPayInfo
        {
            get
            {
                if (_tenPayInfo == null)
                {
                    _tenPayInfo =
                        TenPayInfoCollection.Data[ConfigurationManager.AppSettings["WeixinPay_PartnerId"]];
                }
                return _tenPayInfo;
            }
        }

        protected override void Initialize(HttpControllerContext controllerContext)
        {
            _ctx = new FsssdqfybjyEntities();
            base.Initialize(controllerContext);
        }

        protected override void Dispose(bool disposing)
        {
            _ctx.Dispose();
            base.Dispose(disposing);
        }

        [HttpGet]
        [ActionName("GetRegDeptList")]
        public GetRegDeptListResponse GetRegDeptList()
        {
            var request = new Request4GetRegDeptList();
            Response4GetRegDeptList response4GetRegDeptList;
            try
            {
                var httpClient = InHttpClient.GetClient();
                var responseMsg = httpClient.PostAsJsonAsync("HisWs/GetRegDeptList", request).Result;
                responseMsg.EnsureSuccessStatusCode();
                response4GetRegDeptList = responseMsg.Content.ReadAsAsync<Response4GetRegDeptList>().Result;
            }
            catch (Exception ex)
            {
                Logger.ErrorFormat("调用院内GetRegDeptList Api出错,信息：{0}", JsonConvert.SerializeObject(ex));

                return new GetRegDeptListResponse
                {
                    ResultCode = "2",
                    ResultMsg = "服务器或网络异常，请联系客服"
                };
            }

            if (response4GetRegDeptList.ResultCode != "0")
            {
                return new GetRegDeptListResponse
                {
                    ResultCode = "2",
                    ResultMsg = response4GetRegDeptList.ResultDesc
                };
            }

            var regDeptList = response4GetRegDeptList.RegDeptList;
            var deptList = _ctx.Departs.Where(x => x.RecStatus == 1).ToList();
            var newDeptList = (from rd in regDeptList
                               join d in deptList on rd.DeptId equals d.DeptId into leftdept
                               from left in leftdept.DefaultIfEmpty()
                               select new GetRegDeptListResponse.Dept()
                               {
                                   BranchName = left == null ? "" : left.Loc,
                                   DepartId = rd.DeptId,
                                   DepartName = rd.DeptName,
                                   RegType = rd.RegType,
                                   RegAmt = rd.RegAmt,
                                   RegCount = rd.RegCount,
                                   RegLimit = rd.RegLimit,
                                   WaitCount = rd.WaitCount,
                                   StartTime = rd.StartTime,
                                   EndTime = rd.EndTime
                               }).OrderBy(x => x.DepartName).ToList();

            return new GetRegDeptListResponse
            {
                ResultCode = "0",
                ResultMsg = "",
                Depts = newDeptList
            };
        }

        [HttpGet]
        [ActionName("GetRegDoctorList")]
        public GetRegDoctorListResponse GetRegDoctorList(string deptId, string doctorId = "")
        {
            //24小时挂号科室  0707 急诊科
            var allDayDepts = ConfigurationManager.AppSettings["CanAppointAllDayDeptList"];
            allDayDepts = allDayDepts ?? "0707";
            var allDayDeptList = allDayDepts.Split(",");

            //非24小时挂号科室，未到7点钟，不能挂号
            if (DateTime.Now.Hour < 7 && !allDayDeptList.Contains(deptId))
            {
                return new GetRegDoctorListResponse()
                {
                    ResultCode = "1",
                    ResultMsg = "很抱歉，现在还不是挂号时间，请您于7点后再挂号。"
                };
            }

            var doctorPhotoBaseUrl = ConfigurationManager.AppSettings["DoctorPhotoWebUrl"];
            if (!doctorPhotoBaseUrl.EndsWith("/"))
            {
                doctorPhotoBaseUrl += "/";
            }

            var directDepts = ConfigurationManager.AppSettings["DerictAppointDeptList"];
            directDepts = directDepts ?? "0707";
            var derictDeptList = directDepts.Split(",");
            if (derictDeptList.Contains(deptId))
            {
                var requestGetRegDeptList = new Request4GetRegDeptList();
                Response4GetRegDeptList response4GetRegDeptList;
                try
                {
                    var httpClient = InHttpClient.GetClient();
                    var responseMsg = httpClient.PostAsJsonAsync("HisWs/GetRegDeptList", requestGetRegDeptList).Result;
                    responseMsg.EnsureSuccessStatusCode();
                    response4GetRegDeptList = responseMsg.Content.ReadAsAsync<Response4GetRegDeptList>().Result;
                }
                catch (Exception ex)
                {
                    Logger.ErrorFormat("调用院内GetRegDeptList Api出错,信息：{0}", JsonConvert.SerializeObject(ex));

                    return new GetRegDoctorListResponse
                    {
                        ResultCode = "2",
                        ResultMsg = "服务器或网络异常，请联系客服"
                    };
                }

                if (response4GetRegDeptList.ResultCode != "0")
                {
                    return new GetRegDoctorListResponse
                    {
                        ResultCode = "2",
                        ResultMsg = response4GetRegDeptList.ResultDesc
                    };
                }

                var directDept = response4GetRegDeptList.RegDeptList.FirstOrDefault(x => x.DeptId == deptId);
                if (directDept == null)
                {
                    return new GetRegDoctorListResponse()
                    {
                        ResultCode = "1",
                        ResultMsg = "无医生排班！"
                    };
                }

                var canRegDept = string.CompareOrdinal(DateTime.Now.ToString("yyy-MM-dd HH:mm:ss"), directDept.StartTime) > 0
                                 && string.CompareOrdinal(DateTime.Now.ToString("yyy-MM-dd HH:mm:ss"), directDept.EndTime) < 0;

                if (!canRegDept)
                {
                    return new GetRegDoctorListResponse()
                    {
                        ResultCode = "1",
                        ResultMsg = "无医生排班！"
                    };
                }

                return new GetRegDoctorListResponse()
                {
                    ResultCode = "0",
                    ResultMsg = "",
                    Doctors = new List<GetRegDoctorListResponse.DoctorInfo>()
                    {
                        new GetRegDoctorListResponse.DoctorInfo
                        {
                            ScheduleId = "",
                            DoctorId = "",
                            DoctorName = "",
                            DoctorPhotoUrl = doctorPhotoBaseUrl + "doctorNoPhoto.jpg",
                            SubjectId = "",
                            SubjectName = "",
                            RegType = directDept.RegType,
                            WaitCount = directDept.WaitCount,
                            LeaveCount = directDept.RegLimit.ToInt32OrDefault() - directDept.RegCount.ToInt32OrDefault(),
                            StartTime = directDept.StartTime,
                            EndTime = directDept.EndTime,
                            State = "开诊",
                        }
                    }
                };
            }

            var request = new Request4GetRegDoctorList();
            request.DeptId = deptId;

            Response4GetRegDoctorList response4GetRegDoctorList;
            try
            {
                var httpClient = InHttpClient.GetClient();
                var responseMsg = httpClient.PostAsJsonAsync("HisWs/GetRegDoctorList", request).Result;
                responseMsg.EnsureSuccessStatusCode();
                response4GetRegDoctorList = responseMsg.Content.ReadAsAsync<Response4GetRegDoctorList>().Result;
            }
            catch (Exception ex)
            {
                Logger.ErrorFormat("调用院内GetRegDeptList Api出错,信息：{0}", JsonConvert.SerializeObject(ex));

                return new GetRegDoctorListResponse
                {
                    ResultCode = "2",
                    ResultMsg = "服务器或网络异常，请联系客服"
                };
            }

            if (response4GetRegDoctorList.ResultCode != "0")
            {
                return new GetRegDoctorListResponse
                {
                    ResultCode = "2",
                    ResultMsg = response4GetRegDoctorList.ResultDesc
                };
            }

            
            //var doctorList = _ctx.Doctors.Where(x => x.DeptId == deptId && x.RecStatus == 1).ToList();
            //var doctorPhotoList = doctorList.ToDictionary(doctor => doctor.DoctorId, doctor => doctor.DoctorName);

            var response4RegDoctorList = response4GetRegDoctorList.RegDoctorList.Where(x => x.State == "开诊");

            var regDoctorList = new List<GetRegDoctorListResponse.DoctorInfo>();
            foreach (var regDoctor in response4RegDoctorList)
            {
                regDoctorList.Add(new GetRegDoctorListResponse.DoctorInfo
                {
                    ScheduleId = regDoctor.ScheduleId,
                    DoctorId = regDoctor.DoctorId,
                    DoctorName = regDoctor.DoctorName,
                    SubjectId = regDoctor.SubjectId,
                    SubjectName = regDoctor.SubjectName,
                    RegAmt = regDoctor.RegAmt,
                    RegType = regDoctor.RegType,
                    WaitCount = regDoctor.WaitCount,
                    LeaveCount = int.Parse(regDoctor.RegLimit) - int.Parse(regDoctor.RegCount),
                    StartTime = regDoctor.StartTime,
                    EndTime = regDoctor.EndTime,
                    State = regDoctor.State,
                    //DoctorPhotoUrl = doctorPhotoList.Keys.Contains(regDoctor.DoctorId)
                    //    ? doctorPhotoBaseUrl + doctorPhotoList[regDoctor.DoctorId] + ".JPG"
                    //    : doctorPhotoBaseUrl + "doctorNoPhoto.jpg" //照片地址
                    DoctorPhotoUrl = doctorPhotoBaseUrl + regDoctor.DoctorName + ".JPG"
                });
                #region 上午只能看上午排班
                //if (string.CompareOrdinal(regDoctor.EndTime, DateTime.Now.ToString("yyy-MM-dd HH:mm:ss")) > 0)
                //{
                //    if (
                //        string.CompareOrdinal(DateTime.Now.ToString("yyy-MM-dd HH:mm:ss"),
                //            DateTime.Now.ToString("yyy-MM-dd" + " 06:00:00")) > 0
                //        &&
                //        string.CompareOrdinal(DateTime.Now.ToString("yyy-MM-dd HH:mm:ss"),
                //            DateTime.Now.ToString("yyy-MM-dd" + " 12:00:00")) < 0)
                //    {
                //        if (
                //            string.CompareOrdinal(regDoctor.EndTime, DateTime.Now.ToString("yyy-MM-dd" + " 12:00:00")) <=
                //            0)
                //        {
                //            regDoctorList.Add(new GetRegDoctorListResponse.DoctorInfo
                //            {
                //                ScheduleId = regDoctor.ScheduleId,
                //                DoctorId = regDoctor.DoctorId,
                //                DoctorName = regDoctor.DoctorName,
                //                SubjectId = regDoctor.SubjectId,
                //                SubjectName = regDoctor.SubjectName,
                //                RegAmt = regDoctor.RegAmt,
                //                RegType = regDoctor.RegType,
                //                WaitCount = regDoctor.WaitCount,
                //                LeaveCount = int.Parse(regDoctor.RegLimit) - int.Parse(regDoctor.RegCount),
                //                StartTime = regDoctor.StartTime,
                //                EndTime = regDoctor.EndTime,
                //                State = regDoctor.State,
                //                //DoctorPhotoUrl = doctorPhotoList.Keys.Contains(regDoctor.DoctorId)
                //                //    ? doctorPhotoBaseUrl + doctorPhotoList[regDoctor.DoctorId] + ".JPG"
                //                //    : doctorPhotoBaseUrl + "doctorNoPhoto.jpg" //照片地址
                //                DoctorPhotoUrl = doctorPhotoBaseUrl + regDoctor.DoctorName + ".JPG"
                //            });
                //        }
                //    }
                //    else if (
                //        string.CompareOrdinal(DateTime.Now.ToString("yyy-MM-dd HH:mm:ss"),
                //            DateTime.Now.ToString("yyy-MM-dd" + " 12:00:00")) > 0)
                //    {
                //        if (
                //            string.CompareOrdinal(regDoctor.StartTime,
                //                DateTime.Now.ToString("yyy-MM-dd" + " 12:00:00")) >= 0)
                //        {
                //            regDoctorList.Add(new GetRegDoctorListResponse.DoctorInfo
                //            {
                //                ScheduleId = regDoctor.ScheduleId,
                //                DoctorId = regDoctor.DoctorId,
                //                DoctorName = regDoctor.DoctorName,
                //                SubjectId = regDoctor.SubjectId,
                //                SubjectName = regDoctor.SubjectName,
                //                RegAmt = regDoctor.RegAmt,
                //                RegType = regDoctor.RegType,
                //                WaitCount = regDoctor.WaitCount,
                //                LeaveCount = int.Parse(regDoctor.RegLimit) - int.Parse(regDoctor.RegCount),
                //                StartTime = regDoctor.StartTime,
                //                EndTime = regDoctor.EndTime,
                //                State = regDoctor.State,
                //                //DoctorPhotoUrl = doctorPhotoList.Keys.Contains(regDoctor.DoctorId)
                //                //    ? doctorPhotoBaseUrl + doctorPhotoList[regDoctor.DoctorId] + ".JPG"
                //                //    : doctorPhotoBaseUrl + "doctorNoPhoto.jpg" //照片地址
                //                DoctorPhotoUrl = doctorPhotoBaseUrl + regDoctor.DoctorName + ".JPG"
                //            });
                //        }
                //    }
                //}
                #endregion
            }

            if (!string.IsNullOrEmpty(doctorId))
            {
                regDoctorList = regDoctorList.Where(x => x.DoctorId == doctorId).ToList();
            }

            regDoctorList = regDoctorList.OrderBy(x => x.RegType).ToList();

            return new GetRegDoctorListResponse()
            {
                ResultCode = "0",
                ResultMsg = "0",
                Doctors = regDoctorList
            };
        }

        [HttpGet]
        [ActionName("GetRegSplitList")]
        public GetRegSplitListResponse GetRegSplitList(string scheduleId, string deptId, string doctorId = "")
        {
            var request = new Request4GetsplitList();
            request.SCHEDULEID = scheduleId;
            request.DeptId = deptId;
            request.doctID = doctorId;

            Response4GetsplitList response4GetRegSplitList;
            try
            {
                var httpClient = InHttpClient.GetClient();
                var responseMsg = httpClient.PostAsJsonAsync("HisWs/GetsplitList", request).Result;
                responseMsg.EnsureSuccessStatusCode();
                response4GetRegSplitList = responseMsg.Content.ReadAsAsync<Response4GetsplitList>().Result;
            }
            catch (Exception ex)
            {
                Logger.ErrorFormat("调用院内GetRegDeptList Api出错,信息：{0}", JsonConvert.SerializeObject(ex));

                return new GetRegSplitListResponse
                {
                    ResultCode = "2",
                    ResultMsg = "服务器或网络异常，请联系客服"
                };
            }

            if (response4GetRegSplitList.ResultCode != "0")
            {
                return new GetRegSplitListResponse
                {
                    ResultCode = "2",
                    ResultMsg = response4GetRegSplitList.ResultDesc
                };
            }

            return new GetRegSplitListResponse()
            {
                ResultCode = "0",
                ResultMsg = "0",
                ScheduleList = response4GetRegSplitList.splitList.Select(x => new GetRegSplitListResponse.Schedule
                {
                    SCHEMA_NO = x.SCHEMA_NO,
                    NUM = x.NUM,
                    BEGIN_TIME = x.BEGIN_TIME.Substring(11, 5),
                    DEPT_CODE = x.DEPT_CODE,
                    DEPT_NAME = x.DEPT_NAME,
                    DOCT_CODE = x.DOCT_CODE,
                    DOCT_NAME = x.DOCT_NAME,
                    END_TIME = x.END_TIME.Substring(11, 5),
                    SEE_DATE = x.SEE_DATE
                }).ToList()
            };
        }

        [HttpGet]
        [ActionName("GetRegConfirmInfo")]
        public GetRegConfirmInfoResponse GetRegConfirmInfo(int cardId, string deptId, string regAmt)
        {
            var azUser = AzUser.GetInApi(Request);
            var card = _ctx.HospCards.FirstOrDefault(x => x.Id == cardId && x.WxUserId == azUser.UserId);
            if (card == null)
            {
                return new GetRegConfirmInfoResponse
                {
                    ResultCode = "1",
                    ResultMsg = "找不到诊疗号信息"
                };
            }

            var getClinPatientInfoResponse = new CardController().GetClinPatientInfo(card.CardNo);
            if (getClinPatientInfoResponse.ResultCode != "0")
            {
                return new GetRegConfirmInfoResponse
                {
                    ResultCode = "1",
                    ResultMsg = getClinPatientInfoResponse.ResultMsg
                };
            }

            //社保登记确认
            var sbConfirmed = "0";
            var clinPatientInfo = getClinPatientInfoResponse.ClinPatientInfo;
            if (clinPatientInfo.PayType == "居民基本医疗保险" || clinPatientInfo.PayType == "职工基本医疗保险")
            {
                sbConfirmed = "1";
            }

            //挂号到科室的需要重新获取其挂号费
            var directDepts = ConfigurationManager.AppSettings["DerictAppointDeptList"];
            directDepts = directDepts ?? "0707";
            var derictDeptList = directDepts.Split(",");
            if (derictDeptList.Contains(deptId))
            {
                var request4GetRegAmt = new Request4GetRegAmt();
                request4GetRegAmt.HosPatId = card.PatientId;
                request4GetRegAmt.CardNo = card.CardNo;
                request4GetRegAmt.ClinNo = "";
                request4GetRegAmt.IdCard = "";
                request4GetRegAmt.ScheduleId = "";
                request4GetRegAmt.DeptId = deptId;
                request4GetRegAmt.DoctorId = "";
                request4GetRegAmt.SubjectId = "";

                Response4GetRegAmt response4GetRegAmt;
                try
                {
                    var httpClient = InHttpClient.GetClient();
                    var responseMsg = httpClient.PostAsJsonAsync("HisWs/GetRegAmt", request4GetRegAmt).Result;
                    responseMsg.EnsureSuccessStatusCode();
                    response4GetRegAmt = responseMsg.Content.ReadAsAsync<Response4GetRegAmt>().Result;
                }
                catch (Exception ex)
                {
                    Logger.ErrorFormat("调用GetRegAmt Api出错,信息：{0}", JsonConvert.SerializeObject(ex));
                    return new GetRegConfirmInfoResponse
                    {
                        ResultCode = "3",
                        ResultMsg = "服务器或网络异常，请联系客服"
                    };
                }

                if (response4GetRegAmt.ResultCode != "0")
                {
                    return new GetRegConfirmInfoResponse
                    {
                        ResultCode = "4",
                        ResultMsg = response4GetRegAmt.ResultDesc
                    };
                }

                regAmt = response4GetRegAmt.RegAmt;
            }

            return new GetRegConfirmInfoResponse()
            {
                ResultCode = "0",
                ResultMsg = "",
                SbConfirmed = sbConfirmed,
                PayType = clinPatientInfo.PayType,
                RegAmt = regAmt
            };
        }

        [HttpGet]
        [ActionName("GetRegAmt")]
        public GetRegConfirmInfoResponse GetRegAmt(int cardId, string deptId,string doctorId,string scheduleId,
            string subjectId, string regAmt)
        {
            var azUser = AzUser.GetInApi(Request);
            var card = _ctx.HospCards.FirstOrDefault(x => x.Id == cardId && x.WxUserId == azUser.UserId);
            if (card == null)
            {
                return new GetRegConfirmInfoResponse
                {
                    ResultCode = "1",
                    ResultMsg = "找不到诊疗号信息"
                };
            }

            var getClinPatientInfoResponse = new CardController().GetClinPatientInfo(card.CardNo);
            if (getClinPatientInfoResponse.ResultCode != "0")
            {
                return new GetRegConfirmInfoResponse
                {
                    ResultCode = "1",
                    ResultMsg = getClinPatientInfoResponse.ResultMsg
                };
            }

            //社保登记确认
            var sbConfirmed = "0";
            var clinPatientInfo = getClinPatientInfoResponse.ClinPatientInfo;
            if (clinPatientInfo.PayType == "居民基本医疗保险" || clinPatientInfo.PayType == "职工基本医疗保险")
            {
                sbConfirmed = "1";
            }

            //挂号到科室的需要重新获取其挂号费
            //var directDepts = ConfigurationManager.AppSettings["DerictAppointDeptList"];
            //directDepts = directDepts ?? "0707";
            //var derictDeptList = directDepts.Split(",");
            //if (derictDeptList.Contains(deptId))
            {
                var request4GetRegAmt = new Request4GetRegAmt();
                request4GetRegAmt.HosPatId = card.PatientId;
                request4GetRegAmt.CardNo = card.CardNo;
                request4GetRegAmt.ClinNo = "";
                request4GetRegAmt.IdCard = "";
                request4GetRegAmt.ScheduleId = scheduleId;
                request4GetRegAmt.DeptId = deptId;
                request4GetRegAmt.DoctorId = doctorId;
                request4GetRegAmt.SubjectId = subjectId;

                Response4GetRegAmt response4GetRegAmt;
                try
                {
                    var httpClient = InHttpClient.GetClient();
                    var responseMsg = httpClient.PostAsJsonAsync("HisWs/GetRegAmt", request4GetRegAmt).Result;
                    responseMsg.EnsureSuccessStatusCode();
                    response4GetRegAmt = responseMsg.Content.ReadAsAsync<Response4GetRegAmt>().Result;
                }
                catch (Exception ex)
                {
                    Logger.ErrorFormat("调用GetRegAmt Api出错,信息：{0}", JsonConvert.SerializeObject(ex));
                    return new GetRegConfirmInfoResponse
                    {
                        ResultCode = "3",
                        ResultMsg = "服务器或网络异常，请联系客服"
                    };
                }

                if (response4GetRegAmt.ResultCode != "0")
                {
                    return new GetRegConfirmInfoResponse
                    {
                        ResultCode = "4",
                        ResultMsg = response4GetRegAmt.ResultDesc
                    };
                }

                regAmt = response4GetRegAmt.RegAmt;
            }

            return new GetRegConfirmInfoResponse()
            {
                ResultCode = "0",
                ResultMsg = "",
                SbConfirmed = sbConfirmed,
                PayType = clinPatientInfo.PayType,
                RegAmt = regAmt
            };
        }
        [HttpGet]
        [ActionName("CreateRegOrder")]
        public CreateRegOrderResponse CreateRegOrder(int cardId, string deptId, string deptName, string doctorId, string doctorName, string scheduleId,
            string subjectId, string startTime, string endTime, string regAmt, string regType, string sbConfirmed, string payType)
        {

            var azUser = AzUser.GetInApi(Request);
            var card = _ctx.HospCards.FirstOrDefault(x => x.Id == cardId && x.WxUserId == azUser.UserId);
            if (card == null)
            {
                return new CreateRegOrderResponse
                {
                    ResultCode = "1",
                    ResultMsg = "找不到诊疗号信息"
                };
            }

            if (string.IsNullOrEmpty(sbConfirmed))
            {
                return new CreateRegOrderResponse
                {
                    ResultCode = "1",
                    ResultMsg = "社保登记确认信息出错，请重新挂号"
                };
            }

            //新建订单
            var order = new ApptOrder
            {
                WxUserId = azUser.UserId,
                OrderType = ApptOrderExtensions.OrderType.直接挂号.ToInt32().ToString(),//直接挂号
                CardNo = card.CardNo,
                CardName = card.Name,
                DeptId = deptId,
                DeptName = deptName,
                DoctorId = doctorId ?? "",
                DoctorName = doctorName ?? "",
                ScheduleId = scheduleId ?? "",
                SubjectId = subjectId ?? "",
                SbConfirmed = sbConfirmed,
                OrderNo = GenerateNewOrderNo(),
                RegDate = DateTime.Now.ToString("yyyy-MM-dd"),
                OrderStatus = ApptOrderExtensions.OrderStatus.未锁号.ToInt32(), //新订单，未锁号（0）
                TimeSlice = "",
                StartTime = startTime,
                EndTime = endTime,
                RegType = regType,
                PayState = ApptOrderExtensions.PayState.未付款.ToInt32().ToString(),
                Fee = regAmt.ToDecimalOrDefault(),
                TreatFee = null,
                OtherFee = null,
                SumFee = regAmt.ToDecimalOrDefault(),
                CreateTime = DateTime.Now,
                NextCheckTime = null,
            };

            _ctx.ApptOrders.Add(order);
            _ctx.SaveChanges();

            // 费用为0的直接设置为支付成功
            //if (order.SumFee == 0)
            //{
            order.PayState = ApptOrderExtensions.PayState.已付款.ToInt32().ToString();
            order.PayTime = DateTime.Now;
            order.WxTransactionId = "0";
            order.OrderStatus = ApptOrderExtensions.OrderStatus.支付成功.ToInt32();
            _ctx.SaveChanges();

            // RMQ 执行取号
            var pickupingProducer = new OrderPickupingProducer();
            pickupingProducer.Publish(new OrderPickupingMsg
            {
                OrderType = OrderType.挂号订单,
                OrderId = order.Id
            });

            return new CreateRegOrderResponse
            {
                ResultCode = "0",
                ResultMsg = "",
                OrderId = order.Id,
                OrderNo = order.OrderNo,
                PayString = ""
            };
            //}

            //order.OrderStatus = ApptOrderExtensions.OrderStatus.支付中.ToInt32();
            //_ctx.SaveChanges();

            //// RMQ 16分钟后如果还是支付中则设置支付失败
            //var payingTimeoutProducer = new OrderPayingTimeoutProducer();
            //payingTimeoutProducer.Publish(new OrderPayingTimeoutMsg
            //{
            //    OrderType = OrderType.挂号订单,
            //    OrderId = order.Id
            //}, 16 * 60 * 1000);

            ////组织 微信 js 支付方法 getBrandWCPayRequest 的参数
            //var payStartTime = System.DateTime.Now.ToString("yyyyMMddHHmmss");
            //var payExpireTime = System.DateTime.Now.AddMinutes(15).ToString("yyyyMMddHHmmss");

            //var payFee = (order.SumFee * 100).ToInt32().ToString();
            //var superWxUserIds = ConfigurationManager.AppSettings["UserIdsForPayMin"].Split(" , ",
            //StringSplitOptions.RemoveEmptyEntries);
            //if (order.WxUserId.HasValue && superWxUserIds.Contains(order.WxUserId.ToStringOrDefault()))
            //{
            //    payFee = "1";
            //}

            //var result = WeixinPayV3Helper.ComposeJsApiParameter("就诊挂号", "AP" + order.OrderNo,
            //      payFee, GetClientIp(), payStartTime, payExpireTime, "Reg/PaySucceed", azUser.OpenId);

            //if (result.ResultCode != "0")
            //{
            //    return new CreateRegOrderResponse
            //    {
            //        ResultCode = "1",
            //        ResultMsg = result.ResultMsg
            //    };
            //}

            //return new CreateRegOrderResponse
            //{
            //    ResultCode = "0",
            //    ResultMsg = "",
            //    PayString = result.Parameter,
            //    OrderId = order.Id,
            //    OrderNo = order.OrderNo
            //};
        }


        /// <summary>
        /// 用户取消支付
        /// </summary>
        /// <param name="orderId">订单id</param>
        /// <returns></returns>
        [HttpGet]
        [ActionName("PayFailed")]
        public PayFailedResponse PayFailed(int orderId)
        {
            var azUser = AzUser.GetInApi(Request);

            var order = _ctx.ApptOrders.IsStatus(ApptOrderExtensions.OrderStatus.支付中)
                    .FirstOrDefault(x => x.WxUserId == azUser.UserId && x.Id == orderId);
            if (order == null)
            {
                return new PayFailedResponse
                {
                    ResultCode = "1",
                    ResultMsg = "订单不存在"
                };
            }

            order.OrderStatus = ApptOrderExtensions.OrderStatus.支付失败.ToInt32();
            _ctx.SaveChanges();

            return new PayFailedResponse
            {
                ResultCode = "0",
                ResultMsg = ""
            };
        }

        /// <summary>
        /// 微信支付通知回调
        /// </summary>
        /// <returns></returns>
        [AllowAnonymous]
        [HttpPost]
        [ActionName("PaySucceed")]
        public HttpResponseMessage PaySucceed()
        {
            var result = WeixinPayV3Helper.ParsePayNotify(Request.RequestUri, Request.Content.ReadAsStringAsync().Result.Copy());

            if (result.ResultCode == "0")//成功
            {
                var transactionId = result.PayOrder.TransactionId;
                lock (PayNotifyLocker)
                {
                    if (_ctx.WxPayNotifyLogs.Any(x => x.TransactionId == transactionId && x.TradeState == 0))
                    {
                        return new HttpResponseMessage
                        {
                            StatusCode = HttpStatusCode.OK,
                            Content = new StringContent(result.SuccessResponse)
                        };
                    }

                    //记录通过验证的支付通知
                    var orderNotifyLog = new WxPayNotifyLog
                    {
                        ServiceVersion = result.PayOrder.ServiceVersion,
                        Attach = result.PayOrder.Attach,
                        BankBillNo = result.PayOrder.BankBillNo,
                        BankType = result.PayOrder.BankType,
                        BuyerAlias = result.PayOrder.BuyerAlias,
                        Discount = result.PayOrder.Discount.ToNullableInt32(),
                        //FeeType = result.PayOrder.FeeType.ToNullableInt32(),
                        InputCharset = result.PayOrder.InputCharset,
                        NotifyId = result.PayOrder.NotifyId,
                        SignType = result.PayOrder.SignType,
                        Sign = result.PayOrder.Sign,
                        SignKeyIndex = result.PayOrder.SignKeyIndex.ToNullableInt32(),
                        //TradeMode = result.PayOrder.TradeMode.ToNullableInt32(),
                        TradeState = result.PayOrder.TradeState.ToNullableInt32(),
                        PayInfo = result.PayOrder.PayInfo,
                        Partner = result.PayOrder.Partner,
                        TotalFee = result.PayOrder.TotalFee.ToNullableInt32(),
                        TransactionId = result.PayOrder.TransactionId,
                        OutTradeNo = result.PayOrder.OutTradeNo,
                        TimerEnd = result.PayOrder.TimeEnd,
                        TransportFee = result.PayOrder.TransportFee.ToNullableInt32(),
                        ProductFee = result.PayOrder.ProductFee.ToNullableInt32(),
                        PostAppId = result.PayUser.AppId,
                        PostTimeStamp = result.PayUser.TimeStamp,
                        PostNonceStr = result.PayUser.NonceStr,
                        PostOpenId = result.PayUser.OpenId,
                        PostAppSignature = result.PayUser.AppSignature,
                        PostIsSubscribe = result.PayUser.IsSubscribe,
                        RecCreateDt = DateTime.Now,
                        Uri = Request.RequestUri.AbsoluteUri,
                        IsVerified = 1
                    };

                    _ctx.WxPayNotifyLogs.Add(orderNotifyLog);
                    _ctx.SaveChanges();


                    if (result.PayOrder.TradeState == "0")
                    {
                        //处理订单 并记录日志
                        if (result.PayOrder.OutTradeNo.StartsWith("AP"))
                        {
                            var orderNo = result.PayOrder.OutTradeNo.Substring(2);
                            var order = _ctx.ApptOrders.FirstOrDefault(x => x.OrderNo == orderNo);
                            if (order != null)
                            {
                                var isFromRefundUserId = false;
                                if (order.WxUserId.HasValue)
                                {
                                    var refundWxUserIds = WebConfigurationManager.AppSettings["UserIdsForMustRefund"].Split(" , ",
                                    StringSplitOptions.RemoveEmptyEntries);
                                    isFromRefundUserId = refundWxUserIds.Contains(order.WxUserId.ToStringOrDefault());
                                }

                                if (order.OrderStatus == ApptOrderExtensions.OrderStatus.支付中.ToInt32())
                                {
                                    order.PayState = ApptOrderExtensions.PayState.已付款.ToInt32().ToString();
                                    order.PayTime = DateTime.ParseExact(result.PayOrder.TimeEnd, "yyyyMMddHHmmss",
                                        CultureInfo.CurrentCulture);
                                    order.WxTransactionId = transactionId;
                                    order.OrderStatus = ApptOrderExtensions.OrderStatus.支付成功.ToInt32();
                                    _ctx.SaveChanges();

                                    //必退的UserId,执行退费操作
                                    if (isFromRefundUserId)
                                    {
                                        // RMQ 执行退费操作
                                        if (order.SumFee > 0)
                                        {
                                            var refundingProducer = new OrderRefundingPickupFailedProducer();
                                            refundingProducer.Publish(new OrderRefundingPickupFailedMsg
                                            {
                                                OrderType = OrderType.挂号订单,
                                                OrderId = order.Id
                                            });
                                        }
                                    }
                                    else
                                    {
                                        // RMQ 执行取号操作
                                        var pickupingProducer = new OrderPickupingProducer();
                                        pickupingProducer.Publish(new OrderPickupingMsg
                                        {
                                            OrderType = Rmq.Center.OrderType.挂号订单,
                                            OrderId = order.Id
                                        });
                                    }
                                }
                                else if (order.OrderStatus == ApptOrderExtensions.OrderStatus.支付失败.ToInt32())
                                {
                                    //His缴费失败，执行退款操作
                                    var refundingProducer = new OrderRefundingPickupFailedProducer();
                                    refundingProducer.Publish(new OrderRefundingPickupFailedMsg
                                    {
                                        OrderType = OrderType.挂号订单,
                                        OrderId = order.Id
                                    });
                                }
                            }
                        }
                    }

                    return new HttpResponseMessage
                    {
                        StatusCode = HttpStatusCode.OK,
                        Content = new StringContent(result.SuccessResponse)
                    };
                }
            }
            #region 记录验证失败的支付通知

            var unverifiedNotifyLog = new WxPayNotifyLog
            {
                Uri = Request.RequestUri.AbsoluteUri,
                IsVerified = 0,
                RecCreateDt = DateTime.Now
            };
            _ctx.WxPayNotifyLogs.Add(unverifiedNotifyLog);
            _ctx.SaveChanges();

            #endregion

            return new HttpResponseMessage
            {
                StatusCode = HttpStatusCode.OK,
                Content = new StringContent(result.FailResponse)
            };
        }

        /// <summary>
        /// 获取挂号状态
        /// </summary>
        /// <param name="orderId"></param>
        /// <returns></returns>
        [HttpGet]
        [ActionName("GetRegStatus")]
        public GetRegStatusResponse GetRegStatus(int orderId)
        {
            var azUser = AzUser.GetInApi(Request);
            var order = _ctx.ApptOrders.FirstOrDefault(x => x.Id == orderId && x.WxUserId == azUser.UserId);
            if (order == null)
            {
                return new GetRegStatusResponse
                {
                    ResultCode = "1",
                    ResultMsg = "订单不存在"
                };
            }

            if (order.OrderStatus == ApptOrderExtensions.OrderStatus.取号中.ToInt32()
                || order.OrderStatus == ApptOrderExtensions.OrderStatus.支付中.ToInt32()
                || order.OrderStatus == ApptOrderExtensions.OrderStatus.支付成功.ToInt32())
            {
                return new GetRegStatusResponse
                {
                    ResultCode = "0",
                    ResultMsg = "",
                    RegStatus = "2",
                    FailedMsg = ""
                };
            }

            if (order.OrderStatus == ApptOrderExtensions.OrderStatus.取号成功.ToInt32())
            {
                return new GetRegStatusResponse
                {
                    ResultCode = "0",
                    ResultMsg = "",
                    RegStatus = "0",
                    FailedMsg = ""
                };
            }

            return new GetRegStatusResponse
            {
                ResultCode = "0",
                ResultMsg = "",
                RegStatus = "1",
                FailedMsg = ""
            };
        }

        [HttpGet]
        [ActionName("GetRegOrderInfo")]
        public GetRegOrderInfoResponse GetRegOrderInfo(int orderId)
        {
            var azUser = AzUser.GetInApi(Request);
            var order = _ctx.ApptOrders.FirstOrDefault(x => x.Id == orderId && x.WxUserId == azUser.UserId);
            if (order == null)
            {
                return new GetRegOrderInfoResponse
                {
                    ResultCode = "1",
                    ResultMsg = "订单不存在"
                };
            }

            var cardName = "";
            var card = _ctx.HospCards.FirstOrDefault(x => x.CardNo == order.CardNo && x.WxUserId == azUser.UserId);
            if (card != null)
            {
                cardName = card.PatientName;
            }

            return new GetRegOrderInfoResponse
            {
                ResultCode = "0",
                ResultMsg = "",
                DeptName = order.DeptName,
                DoctorName = order.DoctorName,
                CardNum = order.CardNo,
                CardName = cardName,
                SumFee = order.SumFee.ToSingleOrDefault().ToString("F2"),
                RegType = order.RegType,
                WaitNo = order.WaitNo,
                WaitCount = order.WaitCount,
                PatType = order.PatType,
                Address = order.Location,
                RegTime = order.FetchTime.ToDateTimeOrDefault().ToString("yyyy-MM-dd HH:mm:ss"),
                RegDate = order.RegDate,
                StartTime = order.StartTime,
                EndTime = order.EndTime,
                PredictTime = order.SuggestBeginTime
            };
        }


        /// <summary>
        /// 获取预约记录
        /// </summary>
        /// <param name="cardNo"></param>
        /// <param name="startDate"></param>
        /// <returns></returns>
        [HttpGet]
        [ActionName("GetRegInfo")]
        public GetRegInfoResponse GetRegInfo(string cardNo, string startDate)
        {
            var request = new Request4GetRegInfo();
            request.HosPatId = "";
            request.ClinNo = "";
            request.IdCard = "";
            request.FlowNo = "";
            request.CardNo = cardNo;
            request.StartDate = startDate;
            request.EndDate = startDate.ToDateTimeOrDefault().AddDays(16).ToString("yyy-MM-dd");

            Response4GetRegInfo response4GetRegInfo;
            try
            {
                var httpClient = InHttpClient.GetClient();
                var responseMsg = httpClient.PostAsJsonAsync("HisWs/GetRegInfo", request).Result;
                responseMsg.EnsureSuccessStatusCode();
                response4GetRegInfo = responseMsg.Content.ReadAsAsync<Response4GetRegInfo>().Result;
            }
            catch (Exception ex)
            {
                Logger.ErrorFormat("调用院内GetRegInfo Api出错,信息：{0}", JsonConvert.SerializeObject(ex));

                return new GetRegInfoResponse
                {
                    ResultCode = "2",
                    ResultMsg = "服务器或网络异常，请联系客服"
                };
            }

            if (response4GetRegInfo.ResultCode != "0")
            {
                return new GetRegInfoResponse
                {
                    ResultCode = "2",
                    ResultMsg = response4GetRegInfo.ResultDesc
                };
            }

            var regInfoList = response4GetRegInfo.RegInfoList.Select(x => new GetRegInfoResponse.RegInfo
            {
                FlowNo = x.FlowNo,
                CardNo = x.CardNo,
                DeptName = x.DeptName,
                DoctorName = x.DoctorName,
                SubjectName = x.SubjectName,
                StartTime = x.StartTime,
                EndTime = x.EndTime,
                RegType = x.RegType,
                RegAmt = x.RegAmt.ToSingleOrDefault().ToString("F2") + " 元",
                RegTime = x.RegTime.ToDateTimeOrDefault().ToString("yyyy-MM-dd HH:mm:ss"),
                WaitNo = x.WaitNo,
                State = x.State
            }).OrderByDescending(x => x.RegTime).ToList();

            return new GetRegInfoResponse()
            {
                ResultCode = "0",
                ResultMsg = "",
                RegInfos = regInfoList
            };
        }

        /// <summary>
        /// 获取预约过的或者当天挂号的医生
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        [ActionName("GetVisitedDoctor")]
        public GetVisitedDoctorResponse GetVisitedDoctor()
        {
            var azUser = AzUser.GetInApi(Request);

            var doctorPhotoBaseUrl = ConfigurationManager.AppSettings["DoctorPhotoWebUrl"];
            if (!doctorPhotoBaseUrl.EndsWith("/"))
            {
                doctorPhotoBaseUrl += "/";
            }

            var bookOrders = _ctx.BookOrders.Where(x => x.WxUserId.Value == azUser.UserId && x.BookStatus == 1)
                .Select(x => new GetVisitedDoctorResponse.DoctorInfo
                {
                    DeptId = x.DeptId,
                    DeptName = x.DeptName,
                    DoctorId = x.DoctorId,
                    DoctorName = x.DoctorName,
                    DoctorPhotoUrl = doctorPhotoBaseUrl + x.DoctorName + ".JPG",
                    RegType = x.RegType,
                    CreateTime = x.CreateTime
                }).ToList();

            var regOrders = _ctx.ApptOrders.Where(x => x.WxUserId.Value == azUser.UserId && x.OrderStatus == 21)
                .Select(x => new GetVisitedDoctorResponse.DoctorInfo
                {
                    DeptId = x.DeptId,
                    DeptName = x.DeptName,
                    DoctorId = x.DoctorId,
                    DoctorName = x.DoctorName,
                    DoctorPhotoUrl = doctorPhotoBaseUrl + x.DoctorName + ".JPG",
                    RegType = x.RegType,
                    CreateTime = x.CreateTime
                }).ToList();

            if (bookOrders.Count == 0 && regOrders.Count == 0)
            {
                return new GetVisitedDoctorResponse()
                {
                    ResultCode = "0",
                    ResultMsg = ""
                };
            }

            var doctorIds = new List<string>();
            var visitedDoctors = new List<GetVisitedDoctorResponse.DoctorInfo> ();
           
            var visitedOrders = bookOrders.Concat(regOrders).OrderByDescending(x => x.CreateTime).ToList();
            foreach (var visitedOrder in visitedOrders)
            {
                if (!doctorIds.Contains(visitedOrder.DoctorId))
                {
                    doctorIds.Add(visitedOrder.DoctorId);
                    visitedDoctors.Add(visitedOrder);
                }
            }

            return new GetVisitedDoctorResponse()
            {
                ResultCode = "0",
                ResultMsg = "",
                DoctorInfos = visitedDoctors
            };
        }

        /// <summary>
        /// 生成挂号订单号
        /// </summary>
        /// <returns></returns>
        public string GenerateNewOrderNo()
        {
            var orderNo = "WX" + DateTime.Now.Date.ToString("yyyyMMdd");
            lock (OrderNoLocker)
            {
                orderNo += (DateTime.Now - DateTime.Now.Date).TotalMilliseconds.ToString("00000000");
                Thread.Sleep(1);
            }

            return orderNo;
        }

        public string GetClientIp()
        {
            if (Request.Properties.ContainsKey("MS_HttpContext"))
            {
                string ip = System.Web.HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
                //判断是否有代理服务器
                if (string.IsNullOrEmpty(ip))
                {
                    //没有代理服务器,如果有代理服务器获取的是代理服务器的IP
                    ip = System.Web.HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
                }

                string pattrn = @"(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])";
                if (!string.IsNullOrEmpty(ip) && System.Text.RegularExpressions.Regex.IsMatch(ip, pattrn))
                {
                    return ip;
                }

                return "127.0.0.1";
            }
            else
            {
                return "127.0.0.1";
            }
        }
    }
}
